home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
FROMUTS
/
UNIXLIB37B
/
src
/
unix
/
c
/
tty
< prev
next >
Wrap
Text File
|
1992-09-04
|
13KB
|
614 lines
static char sccs_id[] = "@(#) tty.c 4.0 "__DATE__" HJR";
/* tty.c (c) Copyright 1990 H.Rogers */
/* SYS V tty device driver for RiscOS */
#include <signal.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include "fcntl.h"
#include "termio.h"
#include "sys/types.h"
#include "sys/unix.h"
#include "sys/dev.h"
#include "sys/tty.h"
#include "sys/os.h"
#include "sys/param.h"
static struct tty *__t; /* current tty */
#define __ttyx(x) /* increment cursor posn. by (x) */ \
(__t->sx += (x), \
__t->del[__t->cx = (__t->cx + 1) & (MAXPATHLEN - 1)] = (x))
static int __ttyicanon(void *buf,int nbyte,struct file *f);
static int __ttyiraw(void *buf,int nbyte,struct file *f);
static int __ttyinput(int c,int iflag);
static void __ttyecho(int c,int oflag,int lflag);
static void __ttydel(int lflag);
static void __ttytab(int oflag);
static void __ttycr(int oflag);
static void __ttynl(int oflag);
static char __ttybaud[0x10] = { 0,9,1,10,11,2,0,3,12,4,13,5,6,7,8,0 };
/* get console window size */
static void __tty_console_gwinsz(register struct winsize *w)
{
static int i[9] = { 132,134,135,133,128,130,129,131,-1 };
int o[8];
int r[10];
r[0] = (int)i; r[1] = (int)o; os_swi(0x31,r);
w->ws_col = o[1] - o[0] + 1;
w->ws_row = o[3] - o[2] + 1;
w->ws_xpixel = o[5] - o[4] + 1;
w->ws_ypixel = o[7] - o[6] + 1;
}
/* set console window size */
static void __tty_console_swinsz(register struct winsize *w)
{
static int i[7] = { 132,135,128,131,4,5,-1 };
int o[6];
int r[10];
register int j;
r[0] = (int)i; r[1] = (int)o; os_swi(0x31,r);
os_vdu(28);
os_vdu(o[0]);
os_vdu(o[1] + w->ws_row - 1);
os_vdu(o[0] + w->ws_col - 1);
os_vdu(o[1]);
os_vdu(24);
j = o[2]; j <<= o[4]; os_vdu(j & 0xff); os_vdu(j>>8);
j = o[3] - (w->ws_ypixel - 1); j <<= o[5]; os_vdu(j & 0xff); os_vdu(j>>8);
j = o[2] + w->ws_xpixel - 1; j <<= o[4]; os_vdu(j & 0xff); os_vdu(j>>8);
j = o[3]; j <<= o[5]; os_vdu(j & 0xff); os_vdu(j>>8);
}
/* read console */
static void __tty_console_gterm(register struct termio *t)
{
int r[3];
os_byte(0xdc,0,0xff,r); t->c_cc[VINTR] = r[1];
os_byte(0xe5,0,0xff,r); if (r[1])
t->c_lflag &= ~ISIG;
else
t->c_lflag |= ISIG;
}
/* set console */
static void __tty_console_sterm(register struct termio *t)
{
os_byte(0xdc,t->c_cc[VINTR],0,0);
if (t->c_lflag & ISIG)
os_byte(0xe5,0,0,0);
else
os_byte(0xe5,0xff,0,0);
}
/* set RS423 */
static void __tty_423_sterm(register struct termio *t)
{
register int i,c;
int r[10];
i = t->c_cflag & CIBAUD; i = i ? (i>>IBSHIFT) : (t->c_cflag & CBAUD);
r[0] = 5; if (r[1] = __ttybaud[i]) os_swi(0x57,r);
i = t->c_cflag & CBAUD;
r[0] = 6; if (r[1] = __ttybaud[i]) os_swi(0x57,r);
i = t->c_cflag;
switch (i & CSIZE)
{
case CS5:
c = 3;
break;
case CS6:
c = 2;
break;
case CS7:
c = 1;
break;
case CS8:
default:
c = 0;
break;
}
if (i & CSTOPB) c |= 0x04;
if (i & PARENB)
{
c |= 0x08;
if (!(i & PARODD)) c |= 0x10;
}
r[0] = 1; r[1] = c; os_swi(0x57,r);
}
int __ttyopen(char *file,int mode,struct file *f)
{
struct tty *_t;
int l;
switch (*(file + 5))
{
case 'c': /* console */
_t = __u->tty + (l = TTY_CON);
__u->flag = (__u->flag & ~__U_TTY) | (TTY_CON<<__U_TTYSHIFT);
break;
case 'r': /* rs423 */
_t = __u->tty + (l = TTY_423);
__u->flag = (__u->flag & ~__U_TTY) | (TTY_423<<__U_TTYSHIFT);
break;
case 't': /* tty */
_t = __u->tty + (l = ((__u->flag & __U_TTY)>>__U_TTYSHIFT));
break;
default:
return(-1);
break;
}
{
register struct termio *t = _t->t;
t->c_iflag = BRKINT|ICRNL|IMAXBEL;
t->c_oflag = OPOST|ONLCR|XTABS;
if (l == TTY_CON)
t->c_cflag = B38400|CS8|CREAD|HUPCL|CLOCAL;
else if (l == TTY_423)
t->c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
t->c_lflag = ISIG|ICANON|ECHO;
t->c_line = 0;
{
static char cc[NCC] = { CINTR,CQUIT,CERASE,CKILL,CEOF,CEOL,CEOL2,
CSWTCH,CSTART,CSTOP,CSUSP,0,CREPRINT,CDISCARD,CWERASE,CLNEXT };
memcpy(t->c_cc,cc,NCC);
}
if (l == TTY_CON)
__tty_console_gterm(t); /* RS423 is set up later */
}
{
register struct winsize *w = _t->w;
if (l == TTY_CON)
__tty_console_gwinsz(w);
else if (l == TTY_423)
{
w->ws_col = 80;
w->ws_row = 25;
w->ws_xpixel = w->ws_ypixel = 0;
}
}
if (l == TTY_CON)
{
_t->out = os_vdu;
_t->in = os_get;
_t->scan = os_inkey;
_t->init = os_console;
_t->flush = os_keyflush;
}
else if (l == TTY_423)
{
_t->out = os_423vdu;
_t->in = os_423get;
_t->scan = os_423inkey;
_t->init = os_423;
_t->flush = os_423flush;
}
_t->buf = _t->ptr = 0; _t->cnt = 0; _t->del = 0; _t->sx = _t->cx = 0;
{
register int *r = f->r;
r[0] = r[1] = r[2] = r[3] = r[4] = 0; r[5] = 0x33;
}
(*(_t->init))();
if (l == TTY_423)
__tty_423_sterm(_t->t);
return(l);
}
int __ttyclose(int l,struct file *f)
{
register struct tty *_t;
_t = __u->tty + l;
if (_t->del) free(_t->del);
if (_t->buf) free(_t->buf);
_t->buf = _t->ptr = 0; _t->cnt = 0; _t->del = 0; _t->sx = _t->cx = 0;
return(0);
}
int __ttyread(int l,void *buf,int nbyte,struct file *f)
{
__t = __u->tty + l;
if (!__t->del)
if (!(__t->del = malloc(MAXPATHLEN))) { errno = ENOMEM; return(-1); }
return((__t->t->c_lflag & ICANON) ? \
__ttyicanon(buf,nbyte,f) : \
__ttyiraw(buf,nbyte,f));
}
static int __ttyicanon(void *buf,register int nbyte,struct file *f)
{
register int c,i;
register char *s;
register int nflag;
register int iflag,oflag,lflag;
register char *cc;
int ceof,ceol,ceol2;
#define F_LNEXT 000001
#define F_MAX 000002
#define F_NDELAY 000004
if (!__t->buf)
{
if (!(__t->buf = malloc(MAXPATHLEN))) { errno = ENOMEM; return(-1); }
__t->cnt = 0; __t->ptr = __t->buf;
}
if (__t == __u->tty)
os_byte(0xe5,0xff,0,0); /* disable SIGINT */
ret:
if (__t->cnt)
{
if (__t == __u->tty)
os_byte(0xe5,0,0,0); /* re-enable SIGINT */
i = (nbyte > __t->cnt) ? __t->cnt : nbyte;
memcpy(buf,__t->ptr,i);
__t->cnt -= i; __t->ptr += i;
return(i);
}
nflag = (f->oflag & O_NDELAY) ? F_NDELAY : 0;
iflag = __t->t->c_iflag; oflag = __t->t->c_oflag; lflag = __t->t->c_lflag;
cc = (char *)__t->t->c_cc;
ceof = cc[VEOF];
if (!(ceol = cc[VEOL])) ceol--;
if (!(ceol2 = cc[VEOL2])) ceol2--;
s = __t->ptr = __t->buf; __t->sx = __t->cx = 0; i = 0;
for (;;)
{
if (i < MAXPATHLEN) nflag &= ~F_MAX; else nflag |= F_MAX;
if (nflag & F_NDELAY) c = (*(__t->scan))(0); else c = (*(__t->in))();
if (c < 0) goto eol;
if (c == '\r' && iflag & IGNCR) continue;
c = __ttyinput(c,iflag);
if (!(nflag & F_LNEXT))
{
if (c == '\n' || c == ceof || c == ceol || c == ceol2)
goto eol;
if (c == cc[VLNEXT])
{ nflag |= F_LNEXT; continue; }
if (c == cc[VERASE])
{ if (i) { __ttydel(lflag); i--; } continue; }
if (c == cc[VWERASE])
{ while (--i >= 0 && isspace(s[i])) __ttydel(lflag); i++;
while (--i >= 0 && !isspace(s[i])) __ttydel(lflag); i++; continue; }
if (c == cc[VKILL])
{ while (--i >= 0) __ttydel(lflag); i++;
if (lflag & ECHOK) __ttynl(oflag); continue; }
if (c == cc[VREPRINT])
{ register int j; __ttyecho(c,oflag,lflag); __ttynl(oflag);
if (!(oflag & ONLRET)) __ttycr(oflag);
for (j = 0; j < i; j++) __ttyecho(s[j],oflag,lflag); continue; }
if (lflag & ISIG)
{
if (c == cc[VINTR])
{ raise(SIGINT); continue; }
if (c == cc[VQUIT])
{ raise(SIGQUIT); continue; }
}
}
else
nflag &= ~F_LNEXT;
if (nflag & F_MAX)
{ if (iflag & IMAXBEL) (*(__t->out))('\007'); }
else
{ __ttyecho(c,oflag,lflag); s[i++] = c; }
}
eol:
if (c != cc[VEOF] && c >= 0)
{ if (!(nflag & F_MAX)) { __ttyecho(c,oflag,lflag); s[i++] = c; } }
if (__t->cnt = i)
goto ret;
else
{
if (__t == __u->tty)
os_byte(0xe5,0,0,0); /* re-enable SIGINT */
return(0);
}
#undef F_LNEXT
#undef F_MAX
#undef F_NDELAY
}
static int __ttyiraw(void *buf,register int nbyte,struct file *f)
{
register int c,i;
register char *s;
register int nflag;
register int iflag,oflag,lflag;
register char *cc;
register unsigned int vm,vt;
#define F_NSCAN 000001
nflag = 0;
iflag = __t->t->c_iflag; oflag = __t->t->c_oflag; lflag = __t->t->c_lflag;
cc = (char *)__t->t->c_cc;
if (f->oflag & O_NDELAY)
vm = vt = 0;
else
{
vm = (cc[VMIN] && cc[VTIME]) ? 1 : cc[VMIN];
vt = cc[VTIME] * 10;
}
if (cc[VMIN] && !cc[VTIME]) nbyte = vm,nflag |= F_NSCAN;
s = buf; i = 0;
while (i < nbyte)
{
if (nflag & F_NSCAN) c = (*(__t->in))(); else c = (*(__t->scan))(vt);
if (c < 0) { if (i >= vm) return(i); else continue; }
if (c == '\r' && iflag & IGNCR) continue;
c = __ttyinput(c,iflag);
if (lflag & ISIG)
{
if (c == cc[VINTR] && __t != __u->tty)
{ raise(SIGINT); continue; }
if (c == cc[VQUIT])
{ raise(SIGQUIT); continue; }
}
__ttyecho(c,oflag,lflag); s[i++] = c;
}
return(i);
#undef F_NSCAN
}
int __ttywrite(int l,void *buf,int nbyte,struct file *f)
{
register int i,c;
register char *s;
register int oflag,lflag;
register char *cc;
register int (*out)(int);
__t = __u->tty + l;
if (!__t->del)
if (!(__t->del = malloc(MAXPATHLEN))) { errno = ENOMEM; return(-1); }
oflag = __t->t->c_oflag; lflag = __t->t->c_lflag;
cc = (char *)__t->t->c_cc;
out = __t->out;
s = buf; i = 0;
while (i < nbyte)
{
c = s[i++];
if ((oflag & (OPOST|OLCUC)) == (OPOST|OLCUC))
if (isupper(c))
c = _tolower(c);
if (c == cc[VERASE])
__ttydel(lflag);
else if (c == '\t')
__ttytab(oflag);
else if (c == '\n')
__ttynl(oflag);
else if (c == '\r')
__ttycr(oflag);
else
{ __ttyx(1); (*out)(c); }
}
return(nbyte);
}
static int __ttyinput(register int c,register int iflag)
{
if (iflag & ISTRIP) c &= 0x7f;
if (iflag & IUCLC)
if (isupper(c)) c += ('a' - 'A');
if (iflag & INLCR)
if (c == '\n') c = '\r';
if (iflag & ICRNL)
if (c == '\r') c = '\n';
return(c);
}
static void __ttyecho(register int c,register int oflag,register int lflag)
{
if (!((lflag & ECHO) || ((c == '\n') && (lflag & ECHONL)))) return;
if (c == '\t')
__ttytab(oflag);
else if (c == '\n')
__ttynl(oflag);
else if (c == '\r')
__ttycr(oflag);
else if (iscntrl(c))
{
__ttyx(2);
(*(__t->out))('^');
(*(__t->out))((c == 0x7f) ? '?' : (c + '@'));
}
else
{
__ttyx(1);
(*(__t->out))(c);
}
}
static void __ttydel(register int lflag)
{
register int x;
if (__t->sx)
{ x = __t->del[__t->cx]; __t->cx = (__t->cx - 1) & (MAXPATHLEN - 1); }
else
x = 1;
__t->sx = (__t->sx > x) ? (__t->sx - x) : 0;
if (lflag & ECHO)
{
if (lflag & ECHOE)
while (x--)
{
(*(__t->out))('\b');
(*(__t->out))(' ');
(*(__t->out))('\b');
}
else
while (x--)
(*(__t->out))('\177');
}
}
static void __ttytab(register int oflag)
{
if ((oflag & (OPOST|XTABS)) == (OPOST|XTABS))
{
register int x;
x = (8 - (__t->sx & 0x7));
__ttyx(x);
while (x--) (*(__t->out))(' ');
}
else
{
__ttyx(1);
(*(__t->out))('\t');
}
}
static void __ttycr(register int oflag)
{
__t->sx = 0;
if ((oflag & (OPOST|OCRNL)) == (OPOST|OCRNL))
(*(__t->out))('\n');
else if ((oflag & (OPOST|ONOCR)) != (OPOST|ONOCR))
(*(__t->out))('\r');
}
static void __ttynl(register int oflag)
{
if (oflag & OPOST)
{
if (oflag & ONLCR)
if (__t->sx || !(oflag & ONOCR))
(*(__t->out))('\r');
if (oflag & (ONLCR|ONLRET))
__t->sx = 0;
}
(*(__t->out))('\n');
}
long __ttylseek(int l,long lpos,int whence,struct file *f)
{ errno = ESPIPE; return(-1); }
int __ttyioctl(int l,int request,void *arg,struct file *f)
{
register struct tty *_t = __u->tty + l;
if (request == TIOCGWINSZ || request == TIOCSWINSZ)
{
register struct winsize *w = _t->w;
if (request == TIOCGWINSZ)
{
if (l == TTY_CON)
__tty_console_gwinsz(w);
memcpy(arg,w,sizeof(struct winsize));
}
else
{
memcpy(w,arg,sizeof(struct winsize));
if (l == TTY_CON)
__tty_console_swinsz(w);
}
}
else
{
register struct termio *t = _t->t;
if (request & TCDRAIN)
{ _t->ptr = _t->buf; _t->cnt = 0; (*(_t->flush))(); }
switch (request & ~TCDRAIN)
{
case TCGETA:
if (l == TTY_CON)
__tty_console_gterm(t);
memcpy(arg,t,sizeof(struct termio));
break;
case TCSETA:
memcpy(t,arg,sizeof(struct termio));
if (l == TTY_CON)
__tty_console_sterm(t);
else if (l == TTY_423)
__tty_423_sterm(t);
break;
case TCSBRK:
if (l == TTY_423 && !arg) os_423break(25);
break;
case 0:
break;
default:
errno = EINVAL;
return(-1);
break;
}
}
return(0);
}